﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Joy.Erp.BasicArchives.Production;
using Joy.Erp.Ufida.Core;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Joy.Erp.Ufida.Production
{
    public class PlanOrderTypeSyncAppService : UfidaAppService, IPlanOrderTypeSyncAppService
    {
        protected IPlanOrderTypeRepository PlanOrderTypeRepository =>
            LazyServiceProvider.LazyGetRequiredService<IPlanOrderTypeRepository>();
        protected IPlanOrderTypeAppService PlanOrderTypeAppService =>
            LazyServiceProvider.LazyGetRequiredService<IPlanOrderTypeAppService>();
        protected IPlanOrderTypeEnumUfidaAppService PlanOrderTypeEnumUfidaAppService =>
            LazyServiceProvider.LazyGetRequiredService<IPlanOrderTypeEnumUfidaAppService>();

        public async Task<AnalysisDto> AnalyzeAsync()
        {
            var analysisDto = new AnalysisDto();
            analysisDto.Id = typeof(PlanOrderType).FullName;

            // 获取U9数据的ID列表
            var u9list = await PlanOrderTypeEnumUfidaAppService.GetAllAsync();
            var u9Ids = u9list.Select(x => x.ID.ToString()).ToHashSet();
            analysisDto.U9Count = u9Ids.Count;

            // 使用数据库查询优化，只查询需要的字段
            var pmcQuery = await PlanOrderTypeRepository.GetQueryableAsync();

            // 获取PMC总数
            analysisDto.Count = await AsyncExecuter.CountAsync(pmcQuery.Where(x => !x.IsDeleted));

            // 获取已同步的SourceKey列表
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => !x.IsDeleted && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );

            // 使用 HashSet 快速计算已同步数量
            analysisDto.AsyncCount = syncedSourceKeys.Count(key => u9Ids.Contains(key));
            analysisDto.UnasyncCount = analysisDto.U9Count - analysisDto.AsyncCount;
            analysisDto.SelfCount = analysisDto.Count - analysisDto.AsyncCount;

            return analysisDto;
        }

        public async Task<List<long>> GetUnasyncIds()
        {
            // 获取U9的所有ID
            var u9list = await PlanOrderTypeEnumUfidaAppService.GetAllAsync();
            var u9Ids = u9list.Select(x => x.ID).ToList();

            // 使用数据库查询，只查询已同步的SourceKey
            var pmcQuery = await PlanOrderTypeRepository.GetQueryableAsync();
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => !x.IsDeleted && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );

            // 使用 HashSet 优化查找性能，时间复杂度从 O(n²) 降到 O(n)
            var syncedSourceKeySet = new HashSet<string>(syncedSourceKeys);

            // 找出未同步的ID
            var unasyncIds = u9Ids
                .Where(id => !syncedSourceKeySet.Contains(id.ToString()))
                .ToList();

            return unasyncIds;
        }

        public async Task<bool> CreateByIdAsync(long id)
        {
            var existPlanOrderType = await PlanOrderTypeAppService.FindBySourceKeyAsync(
                id.ToString(),
                SourceConfig.SourceType
            );
            if (existPlanOrderType != null)
                return true;

            var planOrderTypeEnumUfidaDto = await PlanOrderTypeEnumUfidaAppService.GetAsync(id);
            if (planOrderTypeEnumUfidaDto == null)
                return false;

            try
            {
                await CreateAsync(planOrderTypeEnumUfidaDto);
                return true;
            }
            catch (Exception ex)
            {
                Logger.LogWarning(
                    ex,
                    $"CreateById‌Async 创建失败，Id: {id}, 数据：{JsonConvert.SerializeObject(planOrderTypeEnumUfidaDto)}, 错误信息：{ex.Message}"
                );
                return false;
            }
        }

        public async Task<int> CreateByIds‌Async(long[] ids)
        {
            if (ids == null || ids.Length == 0)
                return 0;

            var successCount = 0;

            // 批量预查询已存在的记录，避免循环查询数据库
            var pmcQuery = await PlanOrderTypeRepository.GetQueryableAsync();
            var idStrings = ids.Select(id => id.ToString()).ToList();
            var existingSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x =>
                        idStrings.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                    )
                    .Select(x => x.SourceKey)
            );
            var existingSet = new HashSet<string>(existingSourceKeys);

            // 过滤出需要创建的ID
            var needCreateIds = ids.Where(id => !existingSet.Contains(id.ToString())).ToList();
            if (needCreateIds.Count == 0)
                return ids.Length;

            // 在一个事务中批量处理，减少事务开销
            using (
                var uow = UnitOfWorkManager.Begin(
                    new Volo.Abp.Uow.AbpUnitOfWorkOptions(),
                    requiresNew: true
                )
            )
            {
                foreach (var id in needCreateIds)
                {
                    try
                    {
                        var planOrderTypeEnumUfidaDto =
                            await PlanOrderTypeEnumUfidaAppService.GetAsync(id);
                        if (planOrderTypeEnumUfidaDto != null)
                        {
                            var result = await CreateAsync(planOrderTypeEnumUfidaDto);
                            if (result != null)
                            {
                                successCount++;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning(ex, $"CreateByIds‌Async 创建失败，Id: {id}");
                    }
                }

                await uow.CompleteAsync();
            }

            return successCount + existingSet.Count;
        }

        private async Task<PlanOrderTypeDto> CreateAsync(
            PlanOrderTypeEnumUfidaDto planOrderTypeEnumUfidaDto
        )
        {
            var planOrderTypeCreateDto = new PlanOrderTypeCreateDto();

            planOrderTypeCreateDto.SourceType = SourceConfig.SourceType;
            planOrderTypeCreateDto.SourceKey = planOrderTypeEnumUfidaDto.ID.ToString();
            planOrderTypeCreateDto.Code = planOrderTypeEnumUfidaDto.Code;
            planOrderTypeCreateDto.DisplayName = planOrderTypeEnumUfidaDto.Name;

            return await PlanOrderTypeAppService.CreateAsync(planOrderTypeCreateDto);
        }

        public async Task<List<long>> GetSyncedIds()
        {
            var u9list = await PlanOrderTypeEnumUfidaAppService.GetAllAsync();
            var u9Ids = u9list.Select(x => x.ID).ToHashSet();
            var pmcQuery = await PlanOrderTypeRepository.GetQueryableAsync();
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => !x.IsDeleted && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );
            return syncedSourceKeys
                .Where(key => u9Ids.Contains(long.Parse(key)))
                .Select(key => long.Parse(key))
                .ToList();
        }

        public async Task<bool> UpdateByIdAsync(long id)
        {
            var exist = await PlanOrderTypeAppService.FindBySourceKeyAsync(
                id.ToString(),
                SourceConfig.SourceType
            );
            if (exist == null)
                return false;
            var u9Dto = await PlanOrderTypeEnumUfidaAppService.GetAsync(id);
            if (u9Dto == null)
                return false;
            try
            {
                await UpdateAsync(exist.Id, u9Dto);
                return true;
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"UpdateByIdAsync 更新失败，Id: {id}");
                return false;
            }
        }

        public async Task<int> UpdateByIdsAsync(long[] ids)
        {
            if (ids == null || ids.Length == 0)
                return 0;
            var successCount = 0;
            Logger.LogInformation($"[批量同步-计划订单类型] 开始处理 {ids.Length} 条更新");
            var pmcQuery = await PlanOrderTypeRepository.GetQueryableAsync();
            var idStrings = ids.Select(id => id.ToString()).ToList();
            var existingEntities = await AsyncExecuter.ToListAsync(
                pmcQuery.Where(x =>
                    idStrings.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );
            if (existingEntities.Count == 0)
            {
                Logger.LogWarning($"[批量同步-计划订单类型] 没有找到需要更新的记录");
                return 0;
            }
            var entityDict = existingEntities.ToDictionary(x => x.SourceKey, x => x);
            var needUpdateIds = ids.Where(id => entityDict.ContainsKey(id.ToString())).ToList();
            if (needUpdateIds.Count == 0)
                return 0;
            var allU9DataDict = new Dictionary<long, PlanOrderTypeEnumUfidaDto>();
            foreach (var id in needUpdateIds)
            {
                try
                {
                    var dto = await PlanOrderTypeEnumUfidaAppService.GetAsync(id);
                    if (dto != null)
                        allU9DataDict[id] = dto;
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-计划订单类型] 获取U9数据失败，Id: {id}");
                }
            }
            if (allU9DataDict.Count == 0)
                return 0;
            var entitiesToUpdate = new List<PlanOrderType>();
            foreach (var id in needUpdateIds)
            {
                try
                {
                    if (!allU9DataDict.TryGetValue(id, out var u9Data))
                        continue;
                    if (!entityDict.TryGetValue(id.ToString(), out var entity))
                        continue;
                    entity.Code = u9Data.Code;
                    entity.DisplayName = u9Data.Name;
                    entitiesToUpdate.Add(entity);
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-计划订单类型] 修改实体失败，Id: {id}");
                }
            }
            if (entitiesToUpdate.Count > 0)
            {
                using (
                    var uow = UnitOfWorkManager.Begin(
                        new Volo.Abp.Uow.AbpUnitOfWorkOptions(),
                        requiresNew: true
                    )
                )
                {
                    try
                    {
                        await PlanOrderTypeRepository.BulkUpdateAsync(
                            entitiesToUpdate,
                            autoSave: false
                        );
                        await uow.CompleteAsync();
                        successCount = entitiesToUpdate.Count;
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning(
                            ex,
                            $"[批量同步-计划订单类型] 批量更新失败，{ex.Message}"
                        );
                    }
                }
            }
            Logger.LogInformation($"[批量同步-计划订单类型] 完成！成功更新 {successCount} 条");
            return successCount;
        }

        private async Task UpdateAsync(
            Guid pmcId,
            PlanOrderTypeEnumUfidaDto planOrderTypeEnumUfidaDto
        )
        {
            var updateDto = new PlanOrderTypeUpdateDto
            {
                Code = planOrderTypeEnumUfidaDto.Code,
                DisplayName = planOrderTypeEnumUfidaDto.Name,
            };
            await PlanOrderTypeAppService.UpdateAsync(pmcId, updateDto);
        }
    }
}
